let app = getApp();

let retryTimes = 0

function getAPIUrl(params) {
  const server = 'https://www.buaazizhu.club:3304/';
  return server + params;
}

//缓存用户登录数据
function saveLoginData(data) {
  //存储登录token等信息
  wx.setStorage({
    data: {
      token: data.token,
      userInfo: data.userInfo
    },
    key: 'login',
  })
  //  存储到全局变量
  if (!app) {
    app = getApp();
  }
  app.loginData = {
    token: data.token,
    userInfo: data.userInfo
  }
}

//检查本地是否存在用户登录数据
function checkLoginData() {
  return new Promise((resolve, reject) => {
    if (!app) {
      app = getApp()
    }
    let getFunc = () => {
      wx.getStorage({
        key: 'login',
        success: res => {
          let data = res.data; 
          console.log("login data: " + data);
          if (data && data.token && data.userInfo) {
            saveLoginData(data)
            resolve(data)
          }
          else {
            reject(res)
          }
        }, fail: e => {
          reject(e);
        }
      })
    }
    if (!app.loginData) {
      getFunc();
    } else {
      if (app.loginData.token && app.loginData.userInfo) {
        resolve(app.loginData)
      } else {
        getFunc()
      }
    }
  })
}

//请求时捕获未登录的状态
function catchUnLogin(funcInfo) {
  //限制重复登录次数为3次
  if (retryTimes < 3) {
    //获取code
    wx.login({
      success: e => {
        if (app.loginData.userInfo) {
          module.exports.login({
            userInfo: app.loginData.userInfo,
            code: e.code
          }).then(() => {
            //记录重复尝试次数
            retryTimes++
            //重复调用请求函数
            funcInfo.func(funcInfo.options).then((res) => {
              if (funcInfo.options.success)
                funcInfo.options.success(res);
              funcInfo.resolve(res);
            }).catch((e) => {
              if (funcInfo.options.fail)
                funcInfo.options.fail(e)
              else
                funcInfo.reject(e);
            })
          }).catch((e) => {
            console.error(funcInfo.funcName + ': 未登录')
            funcInfo.reject({ err: funcInfo.funcName + ': 未登录', errMsg: '未登录' })
          })
        } else {
          console.error(funcInfo.funcName + ': 未登录')
          funcInfo.reject({ err: funcInfo.funcName + ': 未登录', errMsg: '未登录' })
        }
      }
    })
  } else {
    retryTimes = 0
    console.error(funcInfo.funcName + ': 未登录')
    funcInfo.reject({ err: funcInfo.funcName + ': 未登录', errMsg: '未登录' })
  }
}

//POST请求函数 params是请求路径（不包含前面的/） data是请求体 funcInfo是调用函数信息
function request(params, data, funcInfo) {
  checkLoginData().then(login => {
    wx.request({
      url: getAPIUrl(params),
      method: 'POST',
      header: {
        'Authorization': 'Bearer ' + login.token
      },
      data: data,
      success: result => {

        //调试使用 发布时请记得注释
        console.log(funcInfo.funcName + "请求体：", data);
        console.log(funcInfo.funcName + "请求结果：", result.data)

        //如果状态码为401 Unauthorized
        if (result.statusCode == 401) {
          catchUnLogin(funcInfo);
          return
        } else if (result.statusCode != 200) { // 如果状态码不是200
          if (funcInfo.options.fail)
            funcInfo.options.fail({ err: result, errMsg: "服务器发生错误" })
          else
            funcInfo.reject({ err: result, errMsg: "服务器发生错误" });
        }

        if (funcInfo.options.success)
          funcInfo.options.success(result)
        funcInfo.resolve(result);

      },

      fail: e => {
        e.func = funcInfo.funcName
        if (funcInfo.options.fail)
          funcInfo.options.fail(e)
        else
          funcInfo.reject(e);
      }
    })
  }).catch(() => {
    catchUnLogin(funcInfo)
  })
}

//向后端调用的登录方法。
//options说明：
//code: wx.login()返回的code。
//success: 调用成功，返回结果的函数。
//fail: 调用失败，返回错误信息的函数。
//也可以使用Promise写法。例如调用时: api.login({code: res.code}).then((res)=>{/*正确登录的逻辑段*/}.catch((e)=>{/*发生错误*/}))
module.exports.login = function (options) {
  let that = this
  return new Promise((resolve, reject) => {

    //检查options
    if (!options.code) {
      reject({ err: 'login: 未提供正确的code', errMsg: "未提供正确的code" });
      return false;
    }
    if (!options.userInfo) {
      reject({ err: 'login: 未提供正确的userInfo', errMsg: "未提供正确的userInfo" });
      return false;
    }

    //先检查是否处于登录态
    that.checkLogin()
    //向后端请求登录
    wx.request({
      url: getAPIUrl('weixin/shared/login1'),
      data: {
        code: options.code,
        userInfo: options.userInfo
      },
      method: 'POST',
      success: function (res) {
        //如果返回数据存在token则记录并返回token
        if (res.data.token) {
          saveLoginData({
            token: res.data.token,
            userInfo: options.userInfo
          });
          if (options.success)
            options.success(res);
          resolve(res);
        } else { //如果不存在则报错
          if (options.fail)
            options.fail({ err: res, errMsg: "服务器反馈错误的token" });
          else
            reject({ err: res, errMsg: "服务器反馈错误的token" });
        }
      },
      fail: function (res) {
        if (options.fail)
          options.fail({ err: res, errMsg: "请求时发生错误" });
        else
          reject({ err: res, errMsg: "请求时发生错误" });
      }
    })
  });
}

//检查是否处于登录态。如果是，回调函数中data将包含token和userInfo, 不是则进入fail
module.exports.checkLogin = function (isDebug) {
  return new Promise((resolve, reject) => {
    //如果isDebug为true则跳过登录, 返回假token
    if (isDebug) {
      resolve({
        data: {
          token: 'hhh',
          userinfo: 'hh'
        }
      })
      return;
    }
    //检查Session是否有效
    wx.checkSession({
      success: () => {
        //检查是否存在登录数据
        checkLoginData().then((res) => {
          resolve({ data: res })
        }).catch((e) => {
          reject({ err: e, errMsg: "本地无已存储的用户登录数据" })
        })
      },
      fail: e => {
        reject({ err: e, errMsg: "Session已失效" });
      }
    })
  })
}

//检查要发布的评论是否合法
function checkComment(options, reject) {
  if (!options.experiment) { reject({ err: "uploadComment: 没有实验序号", errMsg: "没有实验序号" }); return false; }
  if ((!options.hdwt) || typeof (options.hdwt) != typeof (1) || options.hdwt > 5 || options.hdwt < 1) {
    reject({ err: "uploadComment: 未填写回答问题详细度", errMsg: "未填写回答问题详细度" }); return false;
  }
  if ((!options.myd) || typeof (options.myd) != typeof (1) || options.myd > 5 || options.myd < 1) {
    reject({ err: "uploadComment: 未填写给分满意度", errMsg: "未填写给分满意度" }); return false;
  }
  if ((!options.jjxxd) || typeof (options.jjxxd) != typeof (1) || options.jjxxd > 5 || options.jjxxd < 1) {
    reject({ err: "uploadComment: 未填写讲解详细度", errMsg: "未填写讲解详细度" }); return false;
  }
  if ((!options.df) || options.df < 0) {
    reject({ err: "uploadComment: 未填写实验积分", errMsg: "未填写实验积分" }); return false;
  }
  if (options.df > 10 || options.df % 1 !== 0) {
    reject({ err: "uploadComment: 实验积分填写有误", errMsg: "实验积分填写有误" }); return false;
  }
  if ((!options.teachername) || typeof (options.teachername) != typeof ("1"))
    options.teachername = ""
  if ((!options.comment) || typeof (options.comment) != typeof ("1"))
    options.comment = ""
  return true
}

//上传评论
module.exports.uploadComment = function (options) {
  return new Promise((resolve, reject) => {

    //发布前检查评论是否合法
    if (!checkComment(options, reject))
      return

    //请求
    request('weixin/api/physics/comments/newcomment', {
      nickName: app.loginData.userInfo.nickName,
      avatarUrl: app.loginData.userInfo.avatarUrl,
      comment: {
        experiment: Number(options.experiment),
        comment: options.comment,
        hdwt: options.hdwt,
        myd: options.myd,
        jjxxd: options.jjxxd,
        df: Number(options.df),
        teachername: options.teachername,
        timeStamp: new Date().getTime()
      }
    }, {
      func: module.exports.uploadComment,
      funcName: 'uploadComment',
      reject: reject,
      resolve: resolve,
      options: options
    })
  })
}

//删除评论 (不可用)
module.exports.deleteComment = function (options) {
  let that = this
  return new Promise((resolve, reject) => {

  })
}

//更新评论
module.exports.updateComment = function (options) {
  return new Promise((resolve, reject) => {

    //检查options
    if (!options.oid) { reject({ err: "updateComment: 没有ObjectId", errMsg: "没有ObjectId" }); return; }
    //发布前检查评论是否合法
    if (!checkComment(options, reject))
      return

    //URL待补充
    request('weixin/api/physics/comments/updatemycomment', {
      oid: options.oid,
      newComment: {
        nickName: app.loginData.userInfo.nickName,
        avatarUrl: app.loginData.userInfo.avatarUrl,
        comment: {
          experiment: Number(options.experiment),
          comment: options.comment,
          hdwt: options.hdwt,
          myd: options.myd,
          jjxxd: options.jjxxd,
          df: Number(options.df),
          teachername: options.teachername,
          timeStamp: new Date().getTime()
        }
      }
    }, {
      func: module.exports.updateComment,
      funcName: 'updateComment',
      reject: reject,
      resolve: resolve,
      options: options
    })
  })
}

//获取评论对象
function getComments(oids) {
  return new Promise((resolve, reject) => {
    if (oids.length == 0) { resolve({ data: { data: [] } }); return; }
    request('weixin/api/physics/comments/getcomments', {
      oid: oids
    }, {
      func: getComments,
      funcName: 'getComments',
      reject: reject,
      resolve: resolve,
      options: oids
    })
  })
}

//JSON属性转换成驼峰命名
function toCamelCase(obj) {
  let reg1 = new RegExp('"nickname"', 'g');
  let reg2 = new RegExp('"avatarurl"', 'g');
  let reg3 = new RegExp('"timestamp"', 'g');
  return JSON.parse(JSON.stringify(obj).replace(reg1, '"nickName"').replace(reg2, '"avatarUrl"').replace(reg3, '"timeStamp"'));
}

//获取评论列表
module.exports.getCommentList = function (options) {

  //检查options
  if (!options.experiment) { reject({ err: "uploadComment: 没有实验序号", errMsg: "没有实验序号" }); return false; }

  return new Promise((resolve, reject) => {
    request('weixin/api/physics/comments/commentlist', {
      experiment: Number(options.experiment)
    }, {
      func: module.exports.getCommentList,
      funcName: 'getCommentList',
      reject: reject,
      resolve: resolve,
      options: options
    })
  })
}

//获取某一个实验的评论
module.exports.getComment = function (options) {
  return new Promise((resolve, reject) => {

    //检查options
    if (!options.experiment) { reject({ err: "getComment: 没有实验序号", errMsg: "没有实验序号" }); return; }
    if (!options.page)
      options.page = 0

    module.exports.getCommentList(options).then((res) => {
      let list = res.data
      //URL待补充
      let reqList = list.others.slice(options.page * 10, (options.page + 1) * 10)
      getComments(reqList).then(result => {
        let tmp = toCamelCase(result.data.data)
        for (let i = 0; i < tmp.length; i++) {
          tmp[i].oid = reqList[i]
        }
        if (options.page == 0 && list.mycomment) {
          list.mycomment.isMine = true
          list.mycomment.oid = list.mycommentid
          let mytmp = toCamelCase(list.mycomment)
          resolve({ data: [mytmp].concat(tmp) })
        } else {
          resolve({ data: tmp })
        }
      })
    })
  })
}

//获取实验详情信息
module.exports.getExpDetail = function (options) {
  return new Promise((resolve, reject) => {

    if (!options.experiment) { reject({ err: "getExpDetail: 没有实验序号", errMsg: "没有实验序号" }); return; }

    wx.request({
      url: getAPIUrl(`physics/details/${options.experiment}/${options.experiment}.json`),
      success: res => {
        if (res.statusCode == 200)
          resolve(res);
        else
          reject({ err: res, errMsg: "请求时发生错误" })
      },
      fail: e => {
        reject({ err: e, errMsg: "请求时发生错误" })
      }
    })
  })
}

//上传实验数据
module.exports.uploadExpData = function (options) {
  return new Promise((resolve, reject) => {

    if (!options.experiment) { reject("uploadExpData: 没有实验序号"); return; }
    if (!options.data) { reject("uploadExpData: 没有实验数据"); return; }
    if (typeof (options.data) == typeof ({}))
      options.data = JSON.stringify(options.data)
    //URL待补充
    request('weixin/api/physics/data/postdata', {
      experiment: options.experiment,
      jsonstr: options.data
    }, {
      func: module.exports.uploadExpData,
      funcName: 'uploadExpData',
      reject: reject,
      resolve: resolve,
      options: options
    })

  })
}

//获取实验数据
module.exports.getExpData = function (options) {
  return new Promise((resolve, reject) => {

    if (!options.experiment) { reject({ err: "getExpData: 没有实验序号", errMsg: "没有实验序号" }); return; }

    //URL待补充
    request('weixin/api/physics/data/getdata', {
      experiment: Number(options.experiment),
    }, {
      func: module.exports.getExpData,
      funcName: 'getExpData',
      reject: reject,
      resolve: resolve,
      options: options
    })
  })
}

//上传反馈内容 请求函数
function requestFeedback(options) {
  return new Promise((resolve, reject) => {
    request('weixin/api/physics/comments/feedback', {
      contact: options.contact,
      feedback: options.feedback,
      timeStamp: options.timeStamp
    }, {
      func: module.exports.uploadFeedback,
      funcName: 'uploadFeedback',
      reject: reject,
      resolve: resolve,
      options: options
    })
  })
}

//上传反馈内容
module.exports.uploadFeedback = function (options) {
  return new Promise((resolve, reject) => {
    if (!options.feedback) {
      reject({ err: "uploadFeedback: 未填写反馈内容", errMsg: "未填写反馈内容" })
      return false
    }
    checkLoginData().then(login => {
      options.timeStamp = new Date().getTime()
      requestFeedback(options).then(res => {
        if (res.data == 0) {
          reject({ err: res, errMsg: "请求时发生错误" })
        } else if (res.data == 1) {
          reject({ err: res, errMsg: "1小时内反馈次数过多" })
        } else if (res.data == 2) {
          resolve(res)
        }
      })
    })
  })
}

module.exports.getCommentStat = function (options) {
  return new Promise((resolve, reject) => {
    checkLoginData().then(login => {
      request('weixin/api/physics/comments/stats', {}, {
        func: module.exports.getCommentStat,
        funcName: 'getCommentStat',
        reject: reject,
        resolve: resolve,
        options: options ? options : {}
      })
    })
  })
}


module.exports.checkUpdate = function () {
  if (wx.canIUse('getUpdateManager')) {
    const updateManager = wx.getUpdateManager()
    updateManager.onCheckForUpdate(function (res) {
      // 请求完新版本信息的回调
      if (res.hasUpdate) {
        updateManager.onUpdateReady(function () {
          updateManager.applyUpdate();
        })
        updateManager.onUpdateFailed(function () {
          // 新的版本下载失败
          wx.showModal({
            title: '新版本小程序下载失败',
            content: '请您关闭小程序并重新打开，以使用最新版本。'
          })
        })
        console.log("checkupdate true")
        return "true"
      }
      console.log("checkupdate false")
      return "false"
    })
  }
  console.log("checkupdate invalid")
  return "invalid"
}